/*
 * 台铃共享项目智能BMS通讯协议
 * 数据帧格式
 * 通讯数据帧包含起始标识、地址标识、通讯命令、数据长度、数据内容、校验数据、结束标识等 7 部
 * 分组成。其中，
 * 起始标识：单字节，内容为0X3A，为固定值
 * 地址标识：单字节，内容为0X16，为固定值
 * 通讯命令：单字节， 内容为各个通讯命令，具体命令参见条款3 内容。
 * 数据长度: 单字节，内容为该通讯数据帧内数据缓冲区内的数据长度，最大值为26。主机发送数据时，
 * 如无特别命令要求，建议设置为1.
 * 数据内容：多字节，内容为具体各个命令对应的数据字节，字节数是不固定的，数量由数据长度部分
 * 的数值确定。主机发送数据时， 如无特别命令要求，建议设置为0.
 * 校验资料：两字节， 内容为通讯数据的累加校验和数据， 包括从地址标识、命令标识、数据长度、数据
 * 内容的等内容的累加和，低字节在前， 高字节在后.
 * 结束标识：两字节， 内容为结束标识1(为固定值0X0D)和结束标识2(为固定值0X0A).
 *
 * 注：校验和计算地址标识、通讯命令、数据长度数据内容
 */
/* CalculateCheckSum代码中校验和计算接口 */
#include "PhyBattery_Prot.h"

#include <string.h>

// #include "BatInfoProcess.h"
// #include "BmsSoc.h"
// #include "Bsp_MCU.h"
// #include "DataOper.h"
// #include "FPara_Aspcfg.h"
// #include "GlobalCfg.h"
// #include "GlobalType.h"
// #include "QTTimer.h"
// #include "VehicleAlarm_AspCfg.h"

/***************************************************************************************************
 * *************************************测试使用的宏定义开始************************************** *
 ***************************************************************************************************/
#define semi_finished_bar_code_string "ACJCBH10AMB11002"
#define SoftwareRevision              0X0000
#define HardwareRevision              0X0010
#define cell_number                   14
#define soh_d                         0X35
#define finished_bar_code             "AEJCBH10AMB11002"
#define software_item_number          "A050200043"
#define hardware_item_number          "B201020149"
#define total_voltage                 42000
#define discharge_current_20A         20000
#define soc_d                         67

static uint16 cell_voltage[cell_number] = {0X1068, 0X1068, 0X1068, 0X1068, 0X1068, 0X1068, 0X1068,  //
                                           0X1068, 0X1068, 0X1068, 0X1068, 0X1068, 0X1068, 0X1068};
/***************************************************************************************************
 * *************************************测试使用的宏定义结束************************************** *
 ***************************************************************************************************/

#define FRAME_LEN_MIN 9  // 9字节

// 获取帧单字节数据
#define frame_start_get(rev_data)               (rev_data[0])
#define frame_address_get(rev_data)             (rev_data[1])
#define frame_cmd_get(rev_data)                 (rev_data[2])
#define frame_data_len_get(rev_data)            (rev_data[3])
#define frame_data_get(rev_data)                (rev_data[4])  // 该宏的使用场景是接收的指令只有9Byte，那么第五位固定是数据位
#define frame_offset_data_get(rev_data, offset) (rev_data[4 + offset])  // 添加了数据偏移，默认rev_data[4]就是第一位数据位
#define frame_checksum_1_get(rev_data, rev_len) (rev_data[rev_len - 4])
#define frame_checksum_2_get(rev_data, rev_len) (rev_data[rev_len - 3])
#define frame_end_1_get(rev_data, rev_len)      (rev_data[rev_len - 2])
#define frame_end_2_get(rev_data, rev_len)      (rev_data[rev_len - 1])

#define celsius_convert_2_kelvin(data) (data + 2731)  // data的单位是0.1℃

#define WORD_16_L_BYTE 0
#define WORD_16_H_BYTE 1

typedef struct {
  uint8 _0 : 1;
  uint8 _1 : 1;
  uint8 _2 : 1;
  uint8 _3 : 1;
  uint8 _4 : 1;
  uint8 _5 : 1;
  uint8 _6 : 1;
  uint8 _7 : 1;
} _8bit;

typedef union {
  uint8 data;
  _8bit bit;
} uint8_bit;

typedef union {
  uint8_bit byte[8];
  uint16    word_16;
  uint32    word_32;
  uint64    word_64;
} typ_iow;

typedef enum {
  frame_start   = 0X3A,  // 起始标识：单字节，内容为0X3A，为固定值
  frame_address = 0X16,  // 地址标识：单字节，内容为0X16，为固定值
  frame_end_1   = 0X0D,  // 结束标识：两字节， 内容为结束标识1(为固定值0X0D)和结束标识2(为固定值0X0A).
  frame_end_2   = 0X0A,  // 结束标识：两字节， 内容为结束标识1(为固定值0X0D)和结束标识2(为固定值0X0A).
} frame_default_data_t;

typedef enum {
  cmd_null                                                     = 0X00,  // 空指令
  cmd_enter_firmware_upgrade                                   = 0X01,  // 进入固件升级(0X01)
  cmd_temp                                                     = 0X08,  // 温度(0X08)
  cmd_voltage                                                  = 0X09,  // 电压(0X09)
  cmd_current                                                  = 0X0A,  // 电流(0X0A)
  cmd_soc                                                      = 0X0D,  // 荷电态SOC(0X0D)
  cmd_residual_capacity                                        = 0X0F,  // 剩余容量(0X0F)
  cmd_maximum_pressure_difference                              = 0X14,  // 最大压差(0X14)
  cmd_cycle_number                                             = 0X17,  // 循环次数(0X17)
  cmd_read_the_semi_finished_bar_code                          = 0X22,  // 读半成品条码(0X22)
  cmd_battery_string_status_information                        = 0X23,  // 电池组状态信息(0X23)
  cmd_voltage_cell_1                                           = 0X24,  // 单体电芯电压(0X24)
  cmd_Voltage_cell_2                                           = 0X25,  // 单体电芯电压(0X25)
  cmd_soh                                                      = 0X0C,  // SOH(0X0C)
  cmd_current_charging_interval                                = 0X47,  // 当前充电间隔时间(0X47)
  cmd_read_the_finished_bar_code                               = 0X7E,  // 读成品条形码(0X7E)
  cmd_read_the_version_information_and_software_product_number = 0X7F,  // 读版本信息及软件品号(0X7F)
  cmd_authentication_discharge_command                         = 0XA0,  // 鉴权放电命令(0XA0)
  cmd_switching_mos_command                                    = 0XA6,  // 开关MOS命令(0XA6)
  cmd_read_mos_command                                         = 0XA7,  // 读取MOS命令(0XA7)
} frame_cmd_t;

typedef enum {
  /* 该枚举鉴权指令使用，实际就是控制放电MOS成功还是失败 */
  authentication_success = 0XAA,
  authentication_fail    = 0X55,
} authentication_t;

static frame_cmd_t frame_cmd_s = cmd_null;
static uint8       recv_temp_buffer[64];  // 该协议最大是指令长度是32Byte，故没有处理可能越界的代码

static uint16 calculate_checksum_16(uint8 *pdata, uint8 length) {
  uint16 sum = 0;
  for (uint8 i = 0; i < length; i++) {
    sum += pdata[i];
  }
  return sum;
}

static BOOLEAN recv_checksum_check(uint8 *pRecvMsg, uint16 RevLen) {
  typ_iow temp;

  // 注：校验和计算地址标识(1Byte)、通讯命令(1Byte)、数据长度(1Byte)、数据内容
  temp.word_16 = calculate_checksum_16(&pRecvMsg[1], (1 + 1 + 1 + frame_data_len_get(pRecvMsg)));
  if (frame_checksum_1_get(pRecvMsg, RevLen) == temp.byte[WORD_16_L_BYTE].data &&  //
      frame_checksum_2_get(pRecvMsg, RevLen) == temp.byte[WORD_16_H_BYTE].data) {
    return TRUE;
  }
  return FALSE;
}

static BOOLEAN frame_receive_check(uint8 *pRecvMsg, uint16 RevLen) {
  if ((frame_start_get(pRecvMsg) == frame_start) &&          //
      (frame_address_get(pRecvMsg) == frame_address) &&      //
      (recv_checksum_check(pRecvMsg, RevLen)) &&             //
      (frame_end_1_get(pRecvMsg, RevLen) == frame_end_1) &&  //
      (frame_end_2_get(pRecvMsg, RevLen) == frame_end_2)) {
    return TRUE;
  }
  return FALSE;
}

static void set_respon_from_cmd_enter_firmware_upgrade(uint8 *SendBuff, uint16 *sendlen) {}
static void set_respon_from_cmd_temp(uint8 *SendBuff, uint16 *sendlen) {
  typ_iow temp;

  /* 协议中只写了读取电池表面温度，没有多个温度的情况，只需要返回一个单体温度即可 */
  temp.word_16           = celsius_convert_2_kelvin(229);
  SendBuff[(*sendlen)++] = 0X02;
  SendBuff[(*sendlen)++] = temp.byte[WORD_16_L_BYTE].data;
  SendBuff[(*sendlen)++] = temp.byte[WORD_16_H_BYTE].data;
}
static void set_respon_from_cmd_voltage(uint8 *SendBuff, uint16 *sendlen) {
  typ_iow temp;
  /* 读取总压指令，单位mV */
  temp.word_16           = total_voltage;
  SendBuff[(*sendlen)++] = 0X02;
  SendBuff[(*sendlen)++] = temp.byte[WORD_16_L_BYTE].data;
  SendBuff[(*sendlen)++] = temp.byte[WORD_16_H_BYTE].data;
}
static void set_respon_from_cmd_current(uint8 *SendBuff, uint16 *sendlen) {
  typ_iow temp;
  /* 读取电流命令，返回数据区前2字节的整数字为电流数值，该数值为有符号的数据，最高位是符号位。单位为mA。 */
  /* 充电电流为正，放电电流为负，如，放电电流 20A 20000＝0x4e20 其补码为 ～0x4e20＋1＝0Xb1E0*/
  temp.word_16           = (~discharge_current_20A) + 1;
  SendBuff[(*sendlen)++] = 0X02;
  SendBuff[(*sendlen)++] = temp.byte[WORD_16_L_BYTE].data;
  SendBuff[(*sendlen)++] = temp.byte[WORD_16_H_BYTE].data;
}
static void set_respon_from_cmd_soc(uint8 *SendBuff, uint16 *sendlen) {
  SendBuff[(*sendlen)++] = 0X01;
  SendBuff[(*sendlen)++] = soc_d;
}
static void set_respon_from_cmd_residual_capacity(uint8 *SendBuff, uint16 *sendlen) {
  // 读取剩余容量命令，返回数据区前2字节整数，单位为mAh剩余容量的数值
  SendBuff[(*sendlen)++] = 0X02;
  SendBuff[(*sendlen)++] = 0XEA;
  SendBuff[(*sendlen)++] = 0X13;
}
static void set_respon_from_cmd_maximum_pressure_difference(uint8 *SendBuff, uint16 *sendlen) {
  // 读最大压差命令，返回数据区前2字节整数，单位为mV。
  SendBuff[(*sendlen)++] = 0X02;
  SendBuff[(*sendlen)++] = 0X64;
  SendBuff[(*sendlen)++] = 0X00;
}
static void set_respon_from_cmd_cycle_number(uint8 *SendBuff, uint16 *sendlen) {
  typ_iow temp;
  // 读取循环次数命令，返回数据区前2字节整数，表示为电池组的循环次数
  temp.word_16           = 0;
  SendBuff[(*sendlen)++] = 0X02;
  SendBuff[(*sendlen)++] = temp.byte[WORD_16_L_BYTE].data;
  SendBuff[(*sendlen)++] = temp.byte[WORD_16_H_BYTE].data;
}
static void set_respon_from_cmd_read_the_semi_finished_bar_code(uint8 *SendBuff, uint16 *sendlen) {
  // 读电池组条码序列号命令，返回N字节ASCII码
  uint8 string_len = strlen(semi_finished_bar_code_string);

  SendBuff[(*sendlen)++] = string_len;
  for (uint8 index = 0; index < string_len; index++) {
    SendBuff[(*sendlen)++] = semi_finished_bar_code_string[index];
  }
}
static void set_respon_from_cmd_battery_string_status_information(uint8 *SendBuff, uint16 *sendlen) {
  typ_iow temp;
  // 读电池组状态信息命令，返回8字节16进制数。
  SendBuff[(*sendlen)++] = 0X08;
  /* Data[0] BMS版本标识 (SoftwareRevision/10)|((HardwareRevision/10)<<4) */
  SendBuff[(*sendlen)++] = (SoftwareRevision / 10) | ((HardwareRevision / 10) << 4);
  /*
  Data[1] 保护状态标识 Bit7 OPTtime 预充超过设定时间保护
    Bit6 Balance Unbalance 保护
    Bit5 Tover 高温温度保护
    Bit4 Oload 放电电流保护
    Bit3 Tover2 低温温度保护
    Bit2 OC充电电流保护
    Bit1 CUV Cell低压保护
    Bit0 COV Cell过压保护
  */
  temp.byte[0].bit._0    = 0;
  temp.byte[0].bit._1    = 0;
  temp.byte[0].bit._2    = 0;
  temp.byte[0].bit._3    = 0;
  temp.byte[0].bit._4    = 0;
  temp.byte[0].bit._5    = 0;
  temp.byte[0].bit._6    = 0;
  temp.byte[0].bit._7    = 0;
  SendBuff[(*sendlen)++] = temp.byte[0].data;
  /* Data[2] Reserve */
  SendBuff[(*sendlen)++] = 0XC4;
  /* Data[3] Reserve */
  SendBuff[(*sendlen)++] = 0X89;
  /* Data[4] Reserve */
  SendBuff[(*sendlen)++] = 0X00;
  /* Data[5] Reserve */
  SendBuff[(*sendlen)++] = 0X00;
  /*
  Data[6] 电池组实时运行异常状态标识 Bit7 Aov Pack 高电压保护
    Bit6 Auv Pack 低电压保护
    Bit5 Lowcap容量低，禁止放电
    Bit4 Charger 充电器错误保护
    Bit3 Nochg 长时间没有充电保护
    Bit2 Badcell Bad cell保护
    Bit0 TemperatureAlert 高温异常报警（充电/放电/静置）
  */
  temp.byte[0].bit._0    = 0;
  temp.byte[0].bit._1    = 0;
  temp.byte[0].bit._2    = 0;
  temp.byte[0].bit._3    = 0;
  temp.byte[0].bit._4    = 0;
  temp.byte[0].bit._5    = 0;
  temp.byte[0].bit._6    = 0;
  temp.byte[0].bit._7    = 0;
  SendBuff[(*sendlen)++] = temp.byte[0].data;
  /* Data[7] Reserve */
  SendBuff[(*sendlen)++] = 0X03;
}
static void set_respon_from_cmd_voltage_cell_1(uint8 *SendBuff, uint16 *sendlen) {
  /* 读取单体电压。电压单位mV */
  typ_iow temp;
  SendBuff[(*sendlen)++] = 0X0E;
  for (uint8 i = 0; i < 7; i++) {
    temp.word_16           = cell_voltage[i];
    SendBuff[(*sendlen)++] = temp.byte[WORD_16_L_BYTE].data;
    SendBuff[(*sendlen)++] = temp.byte[WORD_16_H_BYTE].data;
  }
}
static void set_respon_from_cmd_Voltage_cell_2(uint8 *SendBuff, uint16 *sendlen) {
  typ_iow temp;
  SendBuff[(*sendlen)++] = 0X0C;
  for (uint8 i = 7; i < 13; i++) {
    temp.word_16           = cell_voltage[i];
    SendBuff[(*sendlen)++] = temp.byte[WORD_16_L_BYTE].data;
    SendBuff[(*sendlen)++] = temp.byte[WORD_16_H_BYTE].data;
  }
}
static void set_respon_from_cmd_soh(uint8 *SendBuff, uint16 *sendlen) {
  SendBuff[(*sendlen)++] = 0X02;
  SendBuff[(*sendlen)++] = soh_d;
  SendBuff[(*sendlen)++] = 0X00;
}
static void set_respon_from_cmd_current_charging_interval(uint8 *SendBuff, uint16 *sendlen) {
  /* 读取当前充电间隔时间命令 */
  SendBuff[(*sendlen)++] = 0X0C;
  /*
  0x0000：客户模式（成品条码烧录90天之后）下充电时间间隔，小时为单位；
   */
  SendBuff[(*sendlen)++] = 0X00;
  SendBuff[(*sendlen)++] = 0X00;

  /* 充电开始时间(1980+40=2020年)11月12 日10:30 */
  SendBuff[(*sendlen)++] = 0X1E;
  SendBuff[(*sendlen)++] = 0X0A;
  SendBuff[(*sendlen)++] = 0X6C;
  SendBuff[(*sendlen)++] = 0X51;

  /* 充电结束时间(1980+40=2020年)11月12 日11:39 */
  SendBuff[(*sendlen)++] = 0X27;
  SendBuff[(*sendlen)++] = 0X0B;
  SendBuff[(*sendlen)++] = 0X6C;
  SendBuff[(*sendlen)++] = 0X51;

  /*
  0x0001：成品模式下（成品条码烧录，未超过90天）充电时间间隔，小时为单位
   */
  SendBuff[(*sendlen)++] = 0X01;
  SendBuff[(*sendlen)++] = 0X00;
}
static void set_respon_from_cmd_read_the_finished_bar_code(uint8 *SendBuff, uint16 *sendlen) {
  // 读电池组条码序列号命令，返回N字节ASCII码
  uint8 string_len = strlen(finished_bar_code);

  SendBuff[(*sendlen)++] = string_len;
  for (uint8 index = 0; index < string_len; index++) {
    SendBuff[(*sendlen)++] = finished_bar_code[index];
  }
}
static void set_respon_from_cmd_read_the_version_information_and_software_product_number(uint8 *SendBuff, uint16 *sendlen) {
  uint8 string_len = 0;
  if /*  */ (frame_data_get(recv_temp_buffer) == 0X00) { /* 读取版本信息 */
    SendBuff[(*sendlen)++] = 0X02;
    SendBuff[(*sendlen)++] = 0X82;
    SendBuff[(*sendlen)++] = 0X64;
  } else if (frame_data_get(recv_temp_buffer) == 0X03) { /* 读软件品号 */
    // 读电池组条码序列号命令，返回N字节ASCII码
    string_len             = strlen(software_item_number);
    SendBuff[(*sendlen)++] = string_len;
    for (uint8 index = 0; index < string_len; index++) {
      SendBuff[(*sendlen)++] = software_item_number[index];
    }

  } else if (frame_data_get(recv_temp_buffer) == 0X04) { /* 读硬件品号 */
    // 读电池组条码序列号命令，返回N字节ASCII码
    string_len             = strlen(hardware_item_number);
    SendBuff[(*sendlen)++] = string_len;
    for (uint8 index = 0; index < string_len; index++) {
      SendBuff[(*sendlen)++] = hardware_item_number[index];
    }
  }
}
static void set_respon_from_cmd_authentication_discharge_command(uint8 *SendBuff, uint16 *sendlen) {
  /* 该指令实际就是控制放电MOS，暂时不允许控制，默认返回控制失败 */
  SendBuff[(*sendlen)++] = 0X01;
  if (0) { /* 控制成功指令，暂时不允许控 */
    SendBuff[(*sendlen)++] = authentication_success;
  } else { /* 控制失败指令 */
    SendBuff[(*sendlen)++] = authentication_fail;
  }
}
static void set_respon_from_cmd_switching_mos_command(uint8 *SendBuff, uint16 *sendlen) {
  /* 该指令控制放电MOS，充电MOS，预充MOS，暂时不允许控制，并且协议对该指令也没描述清除 */
  if /*  */ (frame_offset_data_get(recv_temp_buffer, 0) == FALSE) {  // 强控放电mos关闭
  } else if (frame_offset_data_get(recv_temp_buffer, 0) == TRUE) {   // 强控放电MOS打开
  }
  if /*  */ (frame_offset_data_get(recv_temp_buffer, 1) == FALSE) {  // 强控充电MOS关闭
  } else if (frame_offset_data_get(recv_temp_buffer, 1) == TRUE) {   // 强控充电MOS打开
  }
  if /*  */ (frame_offset_data_get(recv_temp_buffer, 2) == FALSE) {  // 强控预充mos关闭
  } else if (frame_offset_data_get(recv_temp_buffer, 2) == TRUE) {   // 强控预充MOS打开
  }
  SendBuff[(*sendlen)++] = 0X01;
  SendBuff[(*sendlen)++] = 0X00;
}
static void set_respon_from_cmd_read_mos_command(uint8 *SendBuff, uint16 *sendlen) {
  SendBuff[(*sendlen)++] = 0X03;

  /* Data[0]:放电MOS状态， 1导通，0关闭 */
  SendBuff[(*sendlen)++] = 0X00;
  /* Data[1]: 充电MOS状态，1导通，0关闭 */
  SendBuff[(*sendlen)++] = 0X00;
  /* Data[2]: 预充MOS状态，1导通，0关闭 */
  SendBuff[(*sendlen)++] = 0X00;
}

static void set_respon_data(uint8 *SendBuff, uint16 *sendlen) {
  switch (frame_cmd_s) {
    case cmd_enter_firmware_upgrade:
      set_respon_from_cmd_enter_firmware_upgrade(SendBuff, sendlen);
      break;
    case cmd_temp:
      set_respon_from_cmd_temp(SendBuff, sendlen);
      break;
    case cmd_voltage:
      set_respon_from_cmd_voltage(SendBuff, sendlen);
      break;
    case cmd_current:
      set_respon_from_cmd_current(SendBuff, sendlen);
      break;
    case cmd_soc:
      set_respon_from_cmd_soc(SendBuff, sendlen);
      break;
    case cmd_residual_capacity:
      set_respon_from_cmd_residual_capacity(SendBuff, sendlen);
      break;
    case cmd_maximum_pressure_difference:
      set_respon_from_cmd_maximum_pressure_difference(SendBuff, sendlen);
      break;
    case cmd_cycle_number:
      set_respon_from_cmd_cycle_number(SendBuff, sendlen);
      break;
    case cmd_read_the_semi_finished_bar_code:
      set_respon_from_cmd_read_the_semi_finished_bar_code(SendBuff, sendlen);
      break;
    case cmd_battery_string_status_information:
      set_respon_from_cmd_battery_string_status_information(SendBuff, sendlen);
      break;
    case cmd_voltage_cell_1:
      set_respon_from_cmd_voltage_cell_1(SendBuff, sendlen);
      break;
    case cmd_Voltage_cell_2:
      set_respon_from_cmd_Voltage_cell_2(SendBuff, sendlen);
      break;
    case cmd_soh:
      set_respon_from_cmd_soh(SendBuff, sendlen);
      break;
    case cmd_current_charging_interval:
      set_respon_from_cmd_current_charging_interval(SendBuff, sendlen);
      break;
    case cmd_read_the_finished_bar_code:
      set_respon_from_cmd_read_the_finished_bar_code(SendBuff, sendlen);
      break;
    case cmd_read_the_version_information_and_software_product_number:
      set_respon_from_cmd_read_the_version_information_and_software_product_number(SendBuff, sendlen);
      break;
    case cmd_authentication_discharge_command:
      set_respon_from_cmd_authentication_discharge_command(SendBuff, sendlen);
      break;
    case cmd_switching_mos_command:
      set_respon_from_cmd_switching_mos_command(SendBuff, sendlen);
      break;
    case cmd_read_mos_command:
      set_respon_from_cmd_read_mos_command(SendBuff, sendlen);
      break;
  }
}

void    PhyBattery_Prot_Init(void) {}
BOOLEAN PhyBattery_Prot_RecvFrame_Process(uint8 *pRecvMsg, uint16 RevLen) {
  /* 数据接收处理接口 */
  uint8 i;
  if (pRecvMsg != NULL &&         //
      RevLen >= FRAME_LEN_MIN &&  //
      frame_receive_check(pRecvMsg, RevLen)) {
    // 校验通过，设置接收指令
    switch (frame_cmd_get(pRecvMsg)) {
      case cmd_enter_firmware_upgrade:
        frame_cmd_s = cmd_enter_firmware_upgrade;
        break;
      case cmd_temp:
        frame_cmd_s = cmd_temp;
        break;
      case cmd_voltage:
        frame_cmd_s = cmd_voltage;
        break;
      case cmd_current:
        frame_cmd_s = cmd_current;
        break;
      case cmd_soc:
        frame_cmd_s = cmd_soc;
        break;
      case cmd_residual_capacity:
        frame_cmd_s = cmd_residual_capacity;
        break;
      case cmd_maximum_pressure_difference:
        frame_cmd_s = cmd_maximum_pressure_difference;
        break;
      case cmd_cycle_number:
        frame_cmd_s = cmd_cycle_number;
        break;
      case cmd_read_the_semi_finished_bar_code:
        frame_cmd_s = cmd_read_the_semi_finished_bar_code;
        break;
      case cmd_battery_string_status_information:
        frame_cmd_s = cmd_battery_string_status_information;
        break;
      case cmd_voltage_cell_1:
        frame_cmd_s = cmd_voltage_cell_1;
        break;
      case cmd_Voltage_cell_2:
        frame_cmd_s = cmd_Voltage_cell_2;
        break;
      case cmd_soh:
        frame_cmd_s = cmd_soh;
        break;
      case cmd_current_charging_interval:
        frame_cmd_s = cmd_current_charging_interval;
        break;
      case cmd_read_the_finished_bar_code:
        frame_cmd_s = cmd_read_the_finished_bar_code;
        break;
      case cmd_read_the_version_information_and_software_product_number:
        frame_cmd_s = cmd_read_the_version_information_and_software_product_number;
        break;
      case cmd_authentication_discharge_command:
        frame_cmd_s = cmd_authentication_discharge_command;
        break;
      case cmd_switching_mos_command:
        frame_cmd_s = cmd_switching_mos_command;
        break;
      case cmd_read_mos_command:
        frame_cmd_s = cmd_read_mos_command;
        break;
      default:
        frame_cmd_s = cmd_null;
        return FALSE;  // 没有相关指令，返回false
    }
    memcpy(recv_temp_buffer, pRecvMsg, RevLen);
    return TRUE;
  }
  return FALSE;
}
uint16 PhyBattery_Prot_SendFrame_Process(uint8 *SendBuff, uint16 BuffLen) {
  typ_iow temp;
  uint16  send_len = 0;
  if (frame_cmd_s != cmd_null) {  // 判断是否真的接收到了数据，真的接收到了则进行组包
    // 进行数据组包
    SendBuff[send_len++] = frame_start;    // 设置起始固定位
    SendBuff[send_len++] = frame_address;  // 设置地址
    SendBuff[send_len++] = frame_cmd_s;    // 设置命令

    // 设置不同帧回执的数据
    set_respon_data(SendBuff, &send_len);

    // 注：校验和计算地址标识(1Byte)、通讯命令(1Byte)、数据长度(1Byte)、数据内容
    temp.word_16         = calculate_checksum_16(&SendBuff[1], (1 + 1 + 1 + frame_data_len_get(SendBuff)));
    SendBuff[send_len++] = temp.byte[WORD_16_L_BYTE].data;
    SendBuff[send_len++] = temp.byte[WORD_16_H_BYTE].data;

    SendBuff[send_len++] = frame_end_1;
    SendBuff[send_len++] = frame_end_2;
    frame_cmd_s          = cmd_null;
  }
  return send_len;
}
